package cn.wolfcode.service.impl;

import cn.wolfcode.common.exception.BusinessException;
import cn.wolfcode.common.web.Result;
import cn.wolfcode.domain.*;
import cn.wolfcode.mapper.OrderInfoMapper;
import cn.wolfcode.mapper.PayLogMapper;
import cn.wolfcode.mapper.RefundLogMapper;
import cn.wolfcode.redis.SeckillRedisKey;
import cn.wolfcode.service.IOrderInfoService;
import cn.wolfcode.service.ISeckillProductService;
import cn.wolfcode.util.IdGenerateUtil;
import cn.wolfcode.web.feign.IntegralFeignApi;
import cn.wolfcode.web.feign.PayFeign;
import cn.wolfcode.web.msg.SeckillCodeMsg;
import io.seata.spring.annotation.GlobalTransactional;
import org.aspectj.weaver.ast.Or;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;

/**
 * Created by wolfcode-lanxw
 */
@Service
public class OrderInfoSeviceImpl implements IOrderInfoService {
    @Autowired
    private ISeckillProductService seckillProductService;
    @Autowired
    private OrderInfoMapper orderInfoMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private PayLogMapper payLogMapper;
    @Autowired
    private RefundLogMapper refundLogMapper;
    @Autowired
    private PayFeign payFeign;
    @Autowired
    private IntegralFeignApi  integralFeignApi;
    @Override
    public OrderInfo findByPhoneAndSeckillId(String phone, Long seckillId) {
        OrderInfo orderInfo= orderInfoMapper.findOrderByPhoneAndSeckillId(phone,seckillId);
        return orderInfo;
    }

    @Override
    @Transactional
    public OrderInfo doSickill(String phone, SeckillProductVo seckillProductVo) {
        //     4扣减数据库库存
        int count = seckillProductService.decrStockCount(seckillProductVo.getId());
        if(count==0){
//            说明发生超卖：抛出异常
            throw new BusinessException(SeckillCodeMsg.SECKILL_STOCK_OVER);
        }
//          判断是否还有库存，如果还存在库存就进行下去并让redis的数据进行原子性递减
        //        5创建秒杀订单
        OrderInfo orderInfo=createOrderInfo(phone,seckillProductVo);
//        将已经秒杀的用户id数据放在一个redis的set中
        String orderSetKey= SeckillRedisKey.SECKILL_ORDER_SET.getRealKey(String.valueOf(seckillProductVo.getId()));
        redisTemplate.opsForSet().add(orderSetKey,phone);
        return orderInfo;
    }

    @Override
    public OrderInfo findByOrderNo(String orderNo) {
        OrderInfo orderInfo = orderInfoMapper.find(orderNo);
        return orderInfo;
    }

    @Override
    @Transactional
    public void cancelOrder(String orderNo) {
        OrderInfo orderInfo = orderInfoMapper.find(orderNo);
        if (orderInfo.STATUS_ARREARAGE.equals(orderInfo.getStatus())){
//            修改订单状态
            int effectCount = orderInfoMapper.updateCancelStatus(orderNo, orderInfo.STATUS_TIMEOUT);
            if (effectCount==0){
                System.out.println("超时支付自己负责");
                return;
            }
//            真实库存回补
            seckillProductService.incrStockCount(orderInfo.getSeckillId());
//            预库存回补
            seckillProductService.syncStockToRedis(orderInfo.getSeckillTime(),orderInfo.getSeckillId());
        }
    }
    @Value("${pay.returnUrl}")
    private String returnUrl;
    @Value("${pay.notifyUrl}")
    private String notifyUrl;
    @Override
    public Result<String> payOnline(String orderNo) {
        OrderInfo orderInfo=this.findByOrderNo(orderNo);
        if (OrderInfo.STATUS_ARREARAGE.equals(orderInfo.getStatus()))
        {
            PayVo vo=new PayVo();
            vo.setOutTradeNo(orderNo);
            vo.setTotalAmount(String.valueOf(orderInfo.getIntergral()));
            vo.setSubject(orderInfo.getProductName());
            vo.setBody(orderInfo.getProductName());
            vo.setReturnUrl(returnUrl);
            vo.setNotifyUrl(notifyUrl);
            System.out.println("异步支付回调的返回地址:"+notifyUrl);
            Result<String> result=payFeign.payOnline(vo);
            return  result;
        }
        System.out.println("重复支付");
        return Result.error(SeckillCodeMsg.PAY_SERVER_ERROR);
    }

    @Override
    public int changePayStatus(String orderNo, Integer status, int payType) {
        int changePayStatus = orderInfoMapper.changePayStatus(orderNo, status, payType);
        return changePayStatus;
    }

    @Override
    public void refundOnline(OrderInfo orderInfo) {
        RefundVo vo=new RefundVo();
        vo.setOutTradeNo(orderInfo.getOrderNo());
        vo.setRefundAmount(String.valueOf(orderInfo.getSeckillPrice()));
        vo.setRefundReason("不想要了");
        Result<Boolean> result=payFeign.refund(vo);
        if (result == null || result.hasError() || !result.getData()) {
            throw  new BusinessException(SeckillCodeMsg.REFUND_ERROR);
        }
        orderInfoMapper.changeRefundStatus(orderInfo.getOrderNo(),OrderInfo.STATUS_REFUND);
    }

    @Override
    public void payIntegral(String orderNo) {
        OrderInfo orderInfo = this.findByOrderNo(orderNo);
        if (OrderInfo.STATUS_ARREARAGE.equals(orderInfo.getStatus())){
            PayLog log=new PayLog();
            log.setOrderNo(orderNo);
            log.setPayTime(new Date());
            log.setTotalAmount(String.valueOf(orderInfo.getSeckillPrice()));
            log.setPayType(OrderInfo.PAYTYPE_INTERGRAL);
            payLogMapper.insert(log);
//        远程调用积分服务  TODO
            OperateIntergralVo vo=new OperateIntergralVo();
            vo.setUserId(orderInfo.getUserId());
            vo.setValue(orderInfo.getIntergral());
//        调用积分服务 TODO
            Result result=integralFeignApi.decrIntegral(vo);
            if (result == null  || result.hasError()) {
                throw new BusinessException(SeckillCodeMsg.INTERGRAL_SERVER_ERROR);
            }
//        修改订单额状态
            int effectCount = orderInfoMapper.changePayStatus(orderNo, OrderInfo.STATUS_ACCOUNT_PAID, OrderInfo.PAYTYPE_INTERGRAL);
            if (effectCount==0){
                throw  new BusinessException(SeckillCodeMsg.PAY_ERROR);
            }
        }
        System.out.println("订单已支付不要重复支付");
    }

    @Override
    @GlobalTransactional
    public void refundIntergral(OrderInfo orderInfo) {
        if (OrderInfo.STATUS_ACCOUNT_PAID.equals(orderInfo.getStatus())){
            RefundLog log=new RefundLog();
            log.setOrderNo(orderInfo.getOrderNo());
            log.setRefundAmount(orderInfo.getIntergral());
            log.setRefundReason("不要了");
            log.setRefundTime(new Date());
            log.setRefundType(OrderInfo.PAYTYPE_INTERGRAL);
            refundLogMapper.insert(log);
//            远程调用服务增加积分
            OperateIntergralVo vo=new OperateIntergralVo();
            vo.setUserId(orderInfo.getUserId());
            vo.setValue(orderInfo.getIntergral());
            Result result=integralFeignApi.incrIntegral(vo);
            if (result == null || result.hasError() ) {
                throw new BusinessException(SeckillCodeMsg.INTERGRAL_SERVER_ERROR);
            }
//            修改订单状态
            int effectCount = orderInfoMapper.changeRefundStatus(orderInfo.getOrderNo(), OrderInfo.STATUS_REFUND);
            if (effectCount==0){
                throw new BusinessException(SeckillCodeMsg.PAY_ERROR);
            }
        }
    }

    private OrderInfo createOrderInfo(String phone, SeckillProductVo seckillProductVo) {
        OrderInfo orderInfo=new OrderInfo();
        BeanUtils.copyProperties(seckillProductVo,orderInfo);
        orderInfo.setUserId(Long.valueOf(phone));
        orderInfo.setCreateDate(new Date());
        orderInfo.setDeliveryAddrId(1L);
        orderInfo.setSeckillDate(seckillProductVo.getStartDate());
        orderInfo.setSeckillTime(seckillProductVo.getTime());
        orderInfo.setOrderNo(String.valueOf(IdGenerateUtil.get().nextId()));
        orderInfo.setSeckillId(seckillProductVo.getId());
        orderInfoMapper.insert(orderInfo);
        return orderInfo;
    }
}
